<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2021/8/14
 * Time: 15:12
 */

namespace App\Http\Controllers\Api;


use App\Models\Order;
use App\Models\Member;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use EasyWeChat\Factory;

class WechatController extends BaseController
{
    protected $config;
    protected $app;

    public function __construct()
    {
        $this->_getConfig();
    }

    public function _getConfig()
    {
        $this->config = [
            // 必要配置
            'app_id'             => env('PUSHER_APP_ID'),
            'app_secret'         => env('PUSHER_APP_SECRET'),
            'mch_id'             => env('PUSHER_MCH_ID'),
            'key'                => env('PUSHER_MCH_SECRET_KEY'),   // API 密钥
            // 如需使用敏感接口（如退款、发送红包等）需要配置 API 证书路径(登录商户平台下载 API 证书)
            'cert_path'          => public_path('/wechat/apiclient_cert.pem'), // XXX: 绝对路径！！！！
            'key_path'           => public_path('/wechat/apiclient_key.pem'),      // XXX: 绝对路径！！！！
            'notify_url'         => env('APP_URL').'/api/payNotify',     // 你也可以在下单时单独设置来想覆盖它
        ];

        $this->app = Factory::payment($this->config);
    }

    /**
     * 订单支付
     * @param int $orderId
     * @param $member
     * @return \Yansongda\Supports\Collection
     * @throws \Exception
     */
    public function payOrder($orderId = 0,$member)
    {
        $orderInfo = Order::where('id',$orderId)->where('mid',$member['id'])->first();
        if(!$orderInfo){
            throw new \Exception('该订单不存在');
        }
        if($orderInfo->status != 1){
            throw new \Exception('该订单不支持支付操作');
        }
        $token = Request()->header('token');
        $memberInfo = Cache::get($token);


        $result = $this->app->order->unify([
            'body' => '下单支付',
            'out_trade_no' => $orderInfo->order_no,
            'total_fee' => $orderInfo->total_price * 100,
            'spbill_create_ip' => '', // 可选，如不传该参数，SDK 将会自动获取相应 IP 地址
            'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
            'openid' => $memberInfo['openid'],
        ]);
        if ($result['return_msg'] == 'OK' && $result['return_code'] == 'SUCCESS' && $result['result_code'] != 'FAIL') {
            Order::where('order_no', $orderInfo->order_no)->update([
                'prepay_id' => $result['prepay_id'],
            ]);
            return  $this->app->jssdk->bridgeConfig($result['prepay_id'], false);
        } else {
            throw new \Exception($result['return_msg']);
        }
    }

    /**
     * 微信支付回调
     */
    public function payNotify()
    {
        $response = $this->app->handlePaidNotify(function ($message, $fail) {
            $orderInfo = Order::query()->where('order_no', '=',$message['out_trade_no'])->first();
            if (!$orderInfo || !in_array($orderInfo->status,[1,33])) {
                return true;
            }

            if ($message['return_code'] === 'SUCCESS') {
                if ($message['result_code'] === 'SUCCESS') {
                    $uid = Member::where('openid', '=', $message['openid'])->value('id');
                    if (false == $uid) {
                       $fail('用戶不合法');
                    }
                    Order::query()->where('id',$orderInfo->id)->update([
                        'status'=>2,
                        'notify_json'   => json_encode($message,JSON_UNESCAPED_UNICODE),
                        'pay_at'    => isset($message['time_end']) ? date('Y-m-d H:i:s',strtotime($message['time_end'])) :date('Y-m-d H:i:s'),
                        'transaction_id'    => isset($message['transaction_id']) && !empty($message['transaction_id']) ? $message['transaction_id'] : ''
                    ]);

                } elseif ($message['result_code'] === 'FAIL') {
                    // 用户支付失败
                    Order::query()->where('id',$orderInfo->id)->update([
                        'order_no'  => orderCreate(),
                    ]);
                    Log::channel('pay_notify')->info('微信支付回调失败：'.json_encode($message,JSON_UNESCAPED_UNICODE));
                }
            } else {
                Order::query()->where('id',$orderInfo->id)->update([
                    'order_no'  => orderCreate(),
                ]);
                $fail('通信失败，请稍后再通知我');
                Log::channel('pay_notify')->info('微信支付回调失败：'.json_encode($message,JSON_UNESCAPED_UNICODE));
            }
        });

        return $response->send();
    }
    /**
     * 订单退款
     */
    public function orderRefund($orderId = 0,$reason = '商家退款')
    {
        $token = Request()->header('token');
        $cacheMember = Cache::get($token);
        $orderInfo = Order::where('id',$orderId)->first();
        if(!$orderInfo){
            throw new \Exception('该订单不存在');
        }
        if($orderInfo->status != 2){
            throw new \Exception('该订单不支持退款操作');
        }
        $orderInfo->out_refund_no = orderRefundCreate();
        $orderInfo->save();
        $result = $this->app->refund->byTransactionId($orderInfo->transaction_id, $orderInfo->out_refund_no, $orderInfo->total_price *100, $orderInfo->total_price* 100, [
            'notify_url'        => env('APP_URL').'/api/refundNotify',
            'refund_desc'       => $reason,
        ]);
        if(!isset($result['return_code']) || $result['return_code'] != 'SUCCESS'){
            throw new \Exception($result['return_msg']);
        }
        if($result['result_code']  == 'SUCCESS'){
            $orderInfo->user_id = $cacheMember['id'];
            $orderInfo->refund_reason = trim($reason);
            $orderInfo->save();
        }else{
             throw new \Exception($result['err_code_des']);
        }
        return $result;

    }

    public function refundNotify()
    {
        $response = $this->app->handleRefundedNotify(function ($message, $reqInfo, $fail) {
            // 其中 $message['req_info'] 获取到的是加密信息
            // $reqInfo 为 message['req_info'] 解密后的信息
            $order = Order::where('order_no',$reqInfo['out_trade_no'])->first();
            if (!$order || $order->status != 2) { // 如果订单不存在 或者 订单已经退过款了
                return true; // 告诉微信，我已经处理完了，订单没找到，别再通知我了
            }
            if($message['return_code'] == 'SUCCESS'){
                if($reqInfo['refund_status'] == 'SUCCESS'){
                    $order->status = 4;
                    $order->refund_id = $reqInfo['refund_id'];
                    $order->refund_at = date('Y-m-d H:i:s');
                    $order->save();
                }else{
                    Log::channel('refund_notify')->info('微信退款回调失败：'.json_encode($message,JSON_UNESCAPED_UNICODE));
                }
            }else{
                $fail('通信失败，请稍后再通知我');
                Log::channel('refund_notify')->info('微信退款回调失败：'.json_encode($message,JSON_UNESCAPED_UNICODE));
            }
            return true; // 返回 true 告诉微信“我已处理完成”
            // 或返回错误原因 $fail('参数格式校验错误');
        });

        return $response;
    }

    public function stable_token()
    {
        $appId = $this->config['app_id'];
        $appSecret = $this->config['app_secret'];
        $grant_type = 'client_credential';
        $token_param = array(
            'grant_type' => $grant_type,
            'appid' => $appId,
            'secret' => $appSecret,
            'force_refresh' => true,
        );
        $url = "https://api.weixin.qq.com/cgi-bin/stable_token";
        $dataRes = curlPost($url, json_encode($token_param),1);
        $data = json_decode($dataRes, true);
        return $data['access_token'];
    }

    //获取token
    public function getAccessToken()
    {

        $cacheKey = $this->config['app_id'] . '@access_token';
        $appId = $this->config['app_id'];
        $appSecret = $this->config['app_secret'];


        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appId}&secret={$appSecret}";

        $http = new \GuzzleHttp\Client;
        $result = $http->get($url);
        $data = json_decode((string) $result->getBody(), true);
        return $data['access_token'];

        //$data = json_decode($result, true);
        // 写入缓存

        Cache::add($cacheKey, $data['access_token'], 5000);    // 7000

        if (!Cache::get($cacheKey)) {
            // 请求API获取 access_token
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appId}&secret={$appSecret}";

            $http = new \GuzzleHttp\Client;
            $result = $http->get($url);
            $data = json_decode((string) $result->getBody(), true);

            //$data = json_decode($result, true);
            // 写入缓存

            Cache::add($cacheKey, $data['access_token'], 5000);    // 7000
        }
        return Cache::get($cacheKey);
    }
    //获取发货订单信息
    public function getWxSendOrderStatus($transaction_id)
    {

        $token = $this->getAccessToken();

        $url = "https://api.weixin.qq.com/wxa/sec/order/get_order?access_token=" . $token;

        $data = [
            'transaction_id' => $transaction_id
        ];
        $data = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

        $result = curlPost($url, $data);

        $result = json_decode($result, true);

        return $result;

    }
    public function set_jump_path()
    {

        $token = $this->getAccessToken();

        $url = "https://api.weixin.qq.com/wxa/sec/order/set_msg_jump_path?access_token=" . $token;

        $data = [
            'path' => 'pages/user/user'
        ];
        $data = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

        curlPost($url, $data);

    }

    // 发货接口
    public function sendDelivery()
    {
        //$this->set_jump_path();

        $token = $this->getAccessToken();
        //$token = $this->stable_token();
        $express_name = "";
        $express_no = "";

        $data = [
            'order_key' => [
                'order_number_type' => 2,
                'transaction_id' => '4200002392202407138355546068'
            ],
            'logistics_type' => 2,//物流模式，发货方式枚举值：1、实体物流配送采用快递公司进行实体物流配送形式 2、同城配送 3、虚拟商品，虚拟商品，例如话费充值，点卡等，无实体配送形式 4、用户自提
            'delivery_mode' => 1,
            'shipping_list' => [
                [
                    'tracking_no' => '',
                    'express_company' => '',
                    'item_desc' => '订单发货信息'
                ]
            ],
            'upload_time' => date('Y-m-d\TH:i:sP', time()),
            'payer' => [
                'openid' => 'osPZ16wLVJYFAKj3vzV5QoR-nVFY'
            ]
        ];


        $urlss = "https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token=" . $token;
        var_dump($urlss);
        $data = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

        $results = curlPost($urlss, $data, 1);

        $results = json_decode($results, true);
        var_dump($results);die;
        if ($results['errcode'] == 0) {
            return true;
        } else {
            return false;
        }
    }



}
